package org.activequant.data.retrieval.mock;

import java.util.Calendar;
import java.util.Iterator;
import java.util.TimeZone;

import org.activequant.core.domainmodel.SeriesSpecification;
import org.activequant.core.domainmodel.data.Candle;
import org.activequant.core.types.TimeFrame;
import org.activequant.core.types.TimeStamp;
import org.activequant.data.retrieval.ISeriesDataIteratorSource;

/**
 * Rather primitive mock candle implementation of ISeriesDataIteratorSource.
 * Internally an anonymous dummy candle iterator is used to generate candle
 * objects according to the given parameters (e.g. distance).
 * <p>
 * Use it for unit testing services that depend on iterator data-sources.
 * <br>
 * <b>History:</b><br>
 *  - [17.01.2008] Created (Erik Nijkamp)<br>
 *
 *  @author Erik Nijkamp
 */
public class MockCandleIteratorSource implements ISeriesDataIteratorSource<Candle> {
	
	private TimeFrame distance = TimeFrame.day();
	
	public void setDistance(TimeFrame val) {
		distance = val;
	}

	public Iterable<Candle> fetch(final SeriesSpecification seriesSpecification) throws Exception {
		return new Iterable<Candle>() {			
			
			public Iterator<Candle> iterator() {
				
				return new Iterator<Candle>() {
					
					private final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
					{
						calendar.setTime(seriesSpecification.getStartTimeStamp().getDate());
						distance.alignCalendar(calendar);
						distance.addToCalendar(calendar);
					}

					public boolean hasNext() {
						return calendar.getTime().before(seriesSpecification.getEndTimeStamp().getDate());
					}

					public Candle next() {
						if(!hasNext()) return null;
						
						distance.addToCalendar(calendar);
						Candle candle = new Candle(seriesSpecification.getInstrumentSpecification());
						candle.setTimeFrame(seriesSpecification.getTimeFrame());
						candle.setTimeStamp(new TimeStamp(calendar.getTime()));
						
						setRandomPrice(candle);
						
						return candle;
					}

					public void remove() {
						
					}				
				};
			}			
		};
	}
	
	private static void setRandomPrice(Candle candle) {
		candle.setVolume(1.0);
		double price1 = 100.0 + Math.random();
		double price2 = 100.0 + Math.random();
		double price3 = 100.0 + Math.random();
		if(price3 < price2) price3 = price2;
		if(price3 < price1) price3 = price1;
		double price4 = 100.0 + Math.random();
		if(price4 > price2) price4 = price2;
		if(price4 > price1) price4 = price1;
		
		candle.setOpenPrice(price1);
		candle.setClosePrice(price2);
		candle.setHighPrice(price3);
		candle.setLowPrice(price4);
	}
}
